﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Resources;
using System.Windows;
using System.Windows.Controls;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Input;
using DevicesInt;

namespace izmer_bizss
{
    /// <summary>
    /// Логика взаимодействия для Control.xaml
    /// </summary>
    public partial class ParametersControl : UserControl, IDisposable
    {
        static readonly ResourceManager Rm = new ResourceManager(typeof(Resources.izmer_bizss));
        private const int TimerInterval = 600;
        private const string NormRegex = @"^[0-9]{1}.[0-9]{1}$";
        private string StandardText { get; set; }
        private const string StandardRegex = @"^0.[0-9]{1,7}$";
        private readonly CultureInfo _curCulture;
        private Task _updateTask;
        private CancellationTokenSource _taskCancelationSource ;
        private bool _editMode;
        private Timer _etalonBoxTimer;
        private Timer _normBoxTimer;

        public BizssController Controller { get; private set; }

        public ParametersControl()
        {
            InitializeComponent();
            StandardText = "0,0";
        }

        private void NormTimerCallBack(object state)
        {
            _normBoxTimer.Change(Timeout.Infinite, Timeout.Infinite);
            var tb = state as TextBox;
            CheckTextBox(tb, NormRegex);
        }

        private void EtalonTimerCallback(object state)
        {
            _etalonBoxTimer.Change(Timeout.Infinite, Timeout.Infinite);
            var tb = state as TextBox;
            CheckTextBox(tb, StandardRegex);
        }

        public ParametersControl(BizssController controller, CultureInfo cultureInfo) : this()
        {
            BizssController.MyCurrentCulture = cultureInfo;
            if (BizssController.MyCurrentCulture == null)
            {
                var cul = CultureInfo.CurrentUICulture;
                if (cul.Name.Contains("ru") || cul.Name.Contains("RU"))
                {
                    BizssController.MyCurrentCulture = CultureInfo.GetCultureInfo("ru");
                }
                else
                {
                    BizssController.MyCurrentCulture = cul;
                }
            }
            _curCulture = BizssController.MyCurrentCulture;
            Visibility = Visibility.Hidden;
            Controller = controller;
            //_curCulture = controller.Culture;
            InitUi();
            StartWorking();
        }

        private void ParametersControl_OnInitialized(object sender, EventArgs e)
        {
            _taskCancelationSource = new CancellationTokenSource();
            _etalonBoxTimer = new Timer(EtalonTimerCallback, EtalonBox, Timeout.Infinite, Timeout.Infinite);
            _normBoxTimer = new Timer(NormTimerCallBack, NormBox, Timeout.Infinite, Timeout.Infinite);
        }

        private void InitUi()
        {
            
            SatelliteLabel.Text = Rm.GetString("Satellites", _curCulture);
            DateLabel.Text = Rm.GetString("Date", _curCulture) + '/' + Rm.GetString("Time", _curCulture);
            EtalonLabel.Text = Rm.GetString("Standard", _curCulture);
            NormLabel.Text = Rm.GetString("Norm", _curCulture);
            DelayLabel.Text = Rm.GetString("Delay", _curCulture);
            DiffLabel.Text = Rm.GetString("Difference", _curCulture);
            StatusLabel.Text = Rm.GetString("Status", _curCulture);
            SetButton.Content = Rm.GetString("Set", _curCulture);
            //ResetButton.Content = Rm.GetString("Reset", _curCulture);
            EditButton.Content = Rm.GetString("Edit", _curCulture);
            NormBox.Tag = "0,0";
            EtalonBox.Tag = "0,0000000";
            NormBox.Text = "0,0";
            EtalonBox.Text = "0,0000000";
            _editMode = true;
            EditButton_OnClick(null, null);
        }

        private void StartWorking()
        {
            _updateTask = new Task(Work, _taskCancelationSource.Token);
            _updateTask.Start();
            
        }

        private void Work()
        {
            while (true)
            {
                if (_taskCancelationSource.IsCancellationRequested)
                    break;
                try
                {
                    if (Controller == null)
                    {
                        
                    }
                    var paramList = Controller.GetParametersList();
                    UpdateStatusText("ok");
                    UpdateParams(paramList);
                }
                catch (Exception ex)
                {
                    OnError(ex.Message);
                }
                Thread.Sleep(150);
            }
        }

        private delegate void VoidDelegate();

        //ToImplement
        private void UpdateParams(IEnumerable<DeviceControl.ParamInfo> parsToSet)
        {
            Dispatcher.Invoke(new VoidDelegate(() =>
            {
                foreach (var info in parsToSet)
                {
                    switch (info.Name)
                    {
                        case StatusParametersNames.SATELLITES_COUNT:
                            SatelliteBox.Text = info.Value;
                            break;
                        case StatusParametersNames.SIGNAL_QUALITY:
                            QSignalBox.Text = info.Value;
                            break;
                        case StatusParametersNames.DATE_TIME:
                            DateBox.Text = info.Value;
                            break;
                        case StatusParametersNames.STANDARD:
                            if (!_editMode)
                                EtalonBox.Text = info.Value;
                            break;
                        case StatusParametersNames.NORM:
                            if(!_editMode)
                                NormBox.Text = info.Value;
                            break;
                        case StatusParametersNames.DELAY:
                            DelayBox.Text = info.Value;
                            break;
                        case StatusParametersNames.DIFFERENCE:
                            DiffBox.Text = info.Value;
                            break;
                    }
                }
            }));
        }

        private void CheckTextBox(TextBox box, string mask)
        {
            Dispatcher.Invoke(new VoidDelegate(() =>
                {
                    if (Regex.IsMatch(box.Text, mask))
                    {
                        box.Tag = box.Text;
                    }
                    else
                    {
                        box.Text = box.Tag.ToString();
                    }
                }));
        }

        private void UpdateStatusText(string message)
        {
            Dispatcher.Invoke(new VoidDelegate(() =>
            {
                if(this.Visibility != Visibility.Visible)
                    Visibility = Visibility.Visible;
                if(StatusBox.Text != null && StatusBox.Text != message)
                    StatusBox.Text = message;
            }));
        }

        private void OnError(string message)
        {
            UpdateStatusText(message);
        }

        private void EtalonBox_OnTextChanged(object sender, TextChangedEventArgs e)
        {
            if (_etalonBoxTimer != null)
                _etalonBoxTimer.Change(TimerInterval, 0);
            //return;
            //var box = sender as TextBox;
            //if (Regex.IsMatch(box.Text, StandardRegex) && box.Text.Count() < 10)
            //{
            //    box.Tag = box.Text;
            //}
            //else
            //{
            //    box.Text = box.Tag.ToString();
            //}
            
        }

        private void NormBox_OnTextChanged(object sender, TextChangedEventArgs e)
        {
            if (_normBoxTimer != null)
                _normBoxTimer.Change(TimerInterval, 0);
            //return;
            //var box = sender as TextBox;
            //if (Regex.IsMatch(box.Text, NormRegex) && box.Text.Count() < 4)
            //{
            //    box.Tag = box.Text;
            //}
            //else
            //{
            //    box.Text = box.Tag.ToString();
            //}
        }

        public void Dispose()
        {
            _taskCancelationSource.Cancel();
            _updateTask.Wait(1000);
        }

        //ToImplement
        private void SetButton_OnClick(object sender, RoutedEventArgs e)
        {
            var chk = Controller.SetParameter(PrepareParams());
            if (chk != "ok")
            {
                MessageBox.Show(chk, "Warning", MessageBoxButton.OK, MessageBoxImage.Warning);
            }
            //_paramsChanged = false;
            EditButton_OnClick(null, null);
        }

        private string PrepareParams()
        {
            var standard = EtalonBox.Text.Split(',')[1];
            var nLen = 7 - standard.Length;
            for (int i = nLen; i > 0; i--)
            {
                standard += "0";
            }
            var norm = NormBox.Text.Remove(1, 1);
            return standard + norm;
        }

        private void EditButton_OnClick(object sender, RoutedEventArgs e)
        {
            if (_editMode)
            {
                EditButton.Content = Rm.GetString("Edit", _curCulture);
                NormBox.IsReadOnly = true;
                EtalonBox.IsReadOnly = true;
                SetButton.IsEnabled = false;
            }
            else
            {
                EditButton.Content = Rm.GetString("Reset", _curCulture);
                NormBox.IsReadOnly = false;
                EtalonBox.IsReadOnly = false;
                SetButton.IsEnabled = true;
            }
            _editMode = !_editMode;
        }
    }
}
